#!/usr/bin/env python
'''PhoneBook

Class that handles the csv file
'''

import re
import os
import csv
import sys
import operator

import Config
import Gui

IDX_NAME = 0
IDX_NUMBER = 1
IDX_COMMENT = 2

class PhoneBook:
    def __init__(self):
        '''Initialize the phone book'''
        if not os.path.exists(Config.get_config('bookpath')):
            Gui.ErrorBox(None, "Can't open archive!")
            sys.exit(False)

        self.__update_list(self.__get_all_from_file())


    def __get_all_from_file(self):
        '''Returns all the items in the phonebook reading them from file'''
        reader = csv.reader(open(Config.get_config('bookpath')))
        return reader


    def get_all(self):
        '''Returns all the items in the phonebook reading them from memory'''
        return self.__reader


    def __update_list(self, list):
        '''Updates the phonebook list in memory'''
        self.__reader = [elem for elem in list]


    def __sort_list(self, list):
        '''Sort in alphabetic order the list'''
        list.sort(lambda x, y: cmp(x[0], y[0]))
        return list


    def get_filtered(self, filter):
        '''
        Return only items that match 'filter'. This method
        should be called within a try...except block since if the
        user pass an invalid regexp it could fail
        '''

        all = self.get_all()

        filtered = []
        compiled_regexp = re.compile(filter, re.IGNORECASE)
        for row in all:
            try:
                match_str = row[IDX_NAME] + row[IDX_NUMBER] + row[IDX_COMMENT]
            except IndexError:
                # jump over eventually missing comments
                match_str = row[IDX_NAME] + row[IDX_NUMBER]

            if compiled_regexp.search(match_str, 0):
                filtered.append(row)

        return filtered


    def add_number(self, name, number, comment):
        '''Add a number to the phonebook'''
        all = self.get_all()
        all.append([name, number, comment])
        self.__update_list(self.__sort_list(all))
        self.write_modifies()


    def update_name(self, idx, new_name):
        '''
        Update the name in the phonebook.
        It doesn't save the modifies to disk. Call get_all in listview
        after you called this function.
        '''
        all = self.get_all()
        mod = []

        i = 0
        for row in all:
            if int(idx) == i:
                tmp_name = new_name
            else:
                tmp_name = row[IDX_NAME]
            mod.append([tmp_name, row[IDX_NUMBER], row[IDX_COMMENT]])
            i = i + 1

        self.__update_list(mod)
        self.write_modifies()

 
    def update_number(self, idx, new_phone):
        '''
        Update the phone number in the phonebook.
        It doesn't save the modifies to disk.
        '''
        all = self.get_all()
        mod = []

        i = 0
        for row in all:
            if int(idx) == i:
                tmp_number = new_phone
            else:
                tmp_number = row[IDX_NUMBER]

            mod.append([row[IDX_NAME], tmp_number, row[IDX_COMMENT]])
            i = i + 1

        self.__update_list(mod)
        self.write_modifies()


    def update_comment(self, idx, new_comment):
        '''
        Update the comment in the phonebook.
        It doesn't save the modifies to disk.
        '''
        all = self.get_all()
        mod = []

        i = 0
        for row in all:
            if int(idx) == i:
                tmp_comment = new_comment
            else:
                tmp_comment = row[IDX_COMMENT]

            mod.append([row[IDX_NAME], row[IDX_NUMBER], tmp_comment])
            i = i + 1

        self.__update_list(mod)
        self.write_modifies()


    def remove_number(self, item_idx):
        '''
        Remove the specified item (a number representing the index in the list)
        from the phonebook
        '''

        all = self.get_all()
        mod = []
        i = 0
        for row in all:
            if i != item_idx:
                mod.append(row)
            i = i + 1

        self.__update_list(mod)
        self.write_modifies()


    def write_modifies(self):
        '''Write the phonebook to disk'''
        f = open(Config.get_config('bookpath'), 'wb')
        writer = csv.writer(f)
        if self.__reader == None:
            self.__update_list(self.__get_all_from_file())

        writer.writerows(self.__reader)
        f.close()

